﻿/* ==============================================================================
 * 功能描述：SocketServerBase  
 * 创 建 者：ljbyo
 * 创建日期：2017/2/6 17:06:18
 * ==============================================================================*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace iPlant.Framework.ACC.WCF.Socket
{

    
    /// SocketServerBase  
    /// </summary>
    public abstract class SocketServerBase
    {
        
        /// Server端Socket
        /// </summary>
        private System.Net.Sockets.Socket _serverSocket = null;
        
        /// Client端Socket
        /// </summary>
        protected System.Net.Sockets.Socket _clientSocket = null;
        
        /// Server端监听线程
        /// </summary>
        private Thread _threadListen = null;
        
        /// Client端监听线程
        /// </summary>
        private Thread _threadClient = null;
        
        /// Socket是否运行状态
        /// </summary>
        protected bool _isRunning = false;

        private int SlEEP_INTEVAL = 100;


        //可配置端口
        private int Port = 3700;
        public SocketServerBase()
        {
        }
        
        /// 自定义端口
        /// </summary>
        /// <param name="port"></param>
        public SocketServerBase(int port)
        {
            Port = port;
        }
        
        /// 获取Socket的运行状态
        /// </summary>
        public bool IsRunning
        {
            get
            {
                return _isRunning;
            }
        }
        
        /// 判断Socket是否有Client连接
        /// </summary>
        public bool IsConnected
        {
            get
            {
                return _clientSocket != null;
            }

        }
        
        /// 开始运行服务端
        /// </summary>
        public void Start()
        {
            try
            {
                _isRunning = true;
                _threadListen = new Thread(new ThreadStart(DoListen));
                _threadListen.IsBackground = true;
                _threadListen.Start();
            }
            catch (System.Net.Sockets.SocketException e)
            {
                throw e;
            }

        }
        
        /// 开始监听
        /// </summary>
        private void DoListen()
        {
            IPEndPoint ip = new IPEndPoint(IPAddress.Any, Port);
            _serverSocket = new System.Net.Sockets.Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                //Thread.Sleep(7000);
                _serverSocket.Bind(ip);
            }
            catch (System.Net.Sockets.SocketException e)
            {
                throw e;
            }

            _serverSocket.Listen(100);
            while (true)
            {
                System.Net.Sockets.Socket clientSocket = _serverSocket.Accept();
                if (_threadClient != null)
                {
                    Stop(true);
                }
                _clientSocket = clientSocket;
                _isRunning = true;
                _threadClient = new Thread(new ThreadStart(RecieveProc));
                _threadClient.IsBackground = true;
                _threadClient.Start();
                SendConnectCmd();
            }
        }
        
        /// 停止服务端运行
        /// </summary>
        /// <param name="ClientOnly"></param>
        public void Stop(bool ClientOnly)
        {
            _isRunning = false;
            //SendDisconnectCmd();
            if (null != _clientSocket)
            {
                try
                {
                    _clientSocket.Close();
                    _clientSocket.Disconnect(true);
                }
                catch
                {
                }
                _clientSocket = null;
            }
            if (null != _threadClient)
            {
                try
                {
                    _threadClient.Abort();
                }
                catch
                {
                }
                _threadClient = null;
            }
            if (ClientOnly)
            {
                return;
            }

            if (null != _threadListen)
            {
                try
                {
                    _threadListen.Abort();
                }
                catch
                {
                }
                _threadListen = null;
            }
            if (null != _serverSocket)
            {
                try
                {
                    _serverSocket.Close();
                    _serverSocket.Disconnect(true);
                }
                catch
                {
                }
                _serverSocket = null;
            }
        }
        
        /// Client消息处理
        /// </summary>
        protected void RecieveProc()
        {
            byte[] buf = new byte[1024 * 8];
            //int len = 0;
            int num = 0;
            int iBytes = 1;
            string msgs = "";
            while (_isRunning)
            {
                try
                {
                    Thread.Sleep(SlEEP_INTEVAL);
                }
                catch
                {
                }
                try
                {
                    //len = 0;
                    if (_clientSocket.Available > 0)
                    {

                        iBytes = _clientSocket.Receive(buf, buf.Length, 0);
                        msgs = System.Text.Encoding.UTF8.GetString(buf, 0, iBytes);

                        //len = _clientSocket.Receive(buf, buf.Length, 0);
                        if (iBytes > 0)
                        {
                            //String msg = System.Text.Encoding.UTF8.GetString(buf, 0, len);
                            string[] cmds = msgs.Split(new string[] { "\\r" }, StringSplitOptions.None);

                            if (cmds != null && cmds.Length > 0)
                            {
                                foreach (string cmd in cmds)
                                {
                                    if (!string.IsNullOrEmpty(cmd))
                                    {
                                        DispatchCmd(cmd);
                                    }
                                }
                            }
                        }
                    }
                    if (_isRunning && num++ > 10 * 5)
                    {
                        num = 0;
                        SendHeartbeatCmd();
                    }
                }
                catch
                {
                    Stop(true);
                }
            }
            _threadClient = null;
        }
        
        /// 分发命令
        /// </summary>
        /// <param name="serverRequest"></param>
        protected abstract void DispatchCmd(string cmd);

        
        /// 发送消息到Client
        /// </summary>
        /// <param name="cmd"></param>
        public abstract int SendCmd(object cmd);

        
        /// 发送连接成功命令到Client
        /// </summary>
        public abstract void SendConnectCmd();
        
        /// 发送断开命令到Client
        /// </summary>
        public abstract void SendDisconnectCmd();
        
        /// 发送心跳命令道Client
        /// </summary>
        public abstract void SendHeartbeatCmd();
    }
}
